﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.IO;
using System.DirectoryServices.Protocols;
using System.Net.NetworkInformation;

namespace ART.Common
{
    /// <summary>
    /// FTP操作类
    /// Create by Jinlong Zhang
    /// </summary>
    public class JFtp
    {

        #region __________创建文件夹__________

        /// <summary>
        /// 创建文件夹:不实现级联创建
        /// 返回：true成功，false失败
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录名，相对路径：如/FTF</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool CreateFtpDirectory(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            ListFtpDirectory(BaseUriStr, "/", UserName, UserPwd);

            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.Timeout = 2000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.MakeDirectory;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                if (FtpResponse.StatusCode == FtpStatusCode.PathnameCreated)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                if (FtpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable || (FtpResponse.StatusCode == FtpStatusCode.Undefined && AimUriStr.Trim() == "/"))
                {
                    //文件已存在，返回True
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
        }

        /// <summary>
        /// 创建文件夹:实现级联创建
        /// 返回：true成功，false失败
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录名，相对路径：如/FTF/FTF1/FTF2/FTF3</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool CreateFtpListDirectory(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
           // CreateFtpDirectory(BaseUriStr, "/", UserName, UserPwd);

            string[] AimUriArray = AimUriStr.TrimStart('/').Split('/');
            string AimUriCache = string.Empty;
            string ParentUri = string.Empty;
            for (int i = 0; i < AimUriArray.Length; i++)
            {
                if (!string.IsNullOrEmpty(AimUriArray[i]))
                {
                    AimUriCache += "/" + AimUriArray[i];
                    ParentUri = AimUriCache.Substring(0, AimUriCache.LastIndexOf('/'));
                    if (ParentUri == "") { ParentUri = "/"; }
                    bool FolderExist = IsExist(AimUriArray[i], BaseUriStr, ParentUri, UserName, UserPwd);
                    if (!FolderExist)
                    {
                        CreateFtpDirectory(BaseUriStr, AimUriCache, UserName, UserPwd);
                    }
                    
                }
            }

            return true;
        }


        #endregion

        #region __________判断文件夹是否存在__________

        /// <summary>
        /// 判断文件夹是否存在
        /// </summary>
        /// <param name="AimUriArray">当前文件夹名称</param>
        /// <param name="BaseUriStr">基Uri字符串：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录名，相对路径：如/FTF/FTF1/FTF2/FTF3</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        public bool IsExist( string AimUriArray,string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            List<string> list = ListFtpDirectory(BaseUriStr, AimUriStr, UserName, UserPwd);
            if (list.Contains(AimUriArray + "|D"))
            {
                return true;
            }
            return false;
        }
        #endregion


        #region __________删除文件夹__________
        /// <summary>
        /// 删除文件夹,不实现级联删除
        /// 返回：true成功，false失败
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录，相对路径：如/FTF/FTFDEL</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool DeleteFtpDirectory(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.Timeout = 2000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.RemoveDirectory;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                if (FtpResponse.StatusCode == FtpStatusCode.FileActionOK)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                //如果返回信息表示文件不可操作或不存在，表明文件夹已经被删除
                if (FtpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    //返回其他错误：可能出现问题
                    FtpResponse.Close();
                    return false;
                }
            }
        }


        /// <summary>
        /// 删除文件夹，实现级联删除
        /// 返回：true成功，false失败
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录，相对路径：如/FTF/FTFDEL</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool DeleteFtpListDirectory(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            List<string> DirectoryDetailList = ListFtpDirectory(BaseUriStr, AimUriStr, UserName, UserPwd);
            foreach (string ListDetail in DirectoryDetailList)
            {
                if (ListDetail.EndsWith("|D"))
                {
                    //删除文件夹内容
                    if (ListFtpDirectory(BaseUriStr, AimUriStr + "/" + ListDetail.Split('|')[0], UserName, UserPwd).Count == 0)
                    {
                        if (!DeleteFtpDirectory(BaseUriStr, AimUriStr + "/" + ListDetail.Split('|')[0], UserName, UserPwd))
                        {
                            return false;
                        }
                    }
                    else
                    {
                        if (!DeleteFtpListDirectory(BaseUriStr, AimUriStr + "/" + ListDetail.Split('|')[0], UserName, UserPwd))
                        {
                            return false;
                        }
                    }
                }
                if (ListDetail.EndsWith("|F"))
                {
                    //删除文件
                    if (!DeleteFtpFile(BaseUriStr, AimUriStr + "/" + ListDetail.Split('|')[0], UserName, UserPwd))
                    {
                        return false;
                    }
                }
            }
            //删除当前文件夹
            if (!DeleteFtpDirectory(BaseUriStr, AimUriStr, UserName, UserPwd))
            {
                return false;
            }

            return true;
        }


        #endregion


        #region __________获取文件夹内文件和文件夹列表信息__________
        /// <summary>
        /// 获取文件夹内文件夹信息
        /// </summary>
        /// <param name="BaseUriStr">基Uri：如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录，相对路径：如/FTF/FTF1</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  List<string> ListFtpDirectory(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.ReadWriteTimeout = 10000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                StreamReader srd = new StreamReader(FtpResponse.GetResponseStream(), Encoding.GetEncoding("GB2312"));
                string ResponseBackStr = srd.ReadToEnd();
                srd.Close();
                FtpResponse.Close();

                string[] ListDetails = ResponseBackStr.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
                List<string> RtnList = new List<string>();
                foreach (string ListDetail in ListDetails)
                {
                    if (ListDetail.StartsWith("d") && (!ListDetail.EndsWith(".")))
                    {
                        string FtpDirName = ListDetail.Substring(ListDetail.IndexOf(':') + 3).TrimStart();
                        RtnList.Add(FtpDirName + "|D");
                        
                    }
                    else if (ListDetail.StartsWith("-"))
                    {
                        //string FtpDirName = ListDetail.Substring(ListDetail.IndexOf(':') + 3).TrimStart();
                        //RtnList.Add(FtpDirName + "|F");
                    }
                }

                return RtnList;
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                FtpResponse.Close();

                return new List<string>();
            }
        }
        #endregion


        #region __________删除指定文件__________
        /// <summary>
        /// 删除指定文件
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串，如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标目录，相对路径：如/FTF/FTFDEL</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool DeleteFtpFile(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.Timeout = 2000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.DeleteFile;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                if (FtpResponse.StatusCode == FtpStatusCode.FileActionOK)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                if (FtpResponse.StatusCode == FtpStatusCode.ActionNotTakenFileUnavailable)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
        }
        #endregion


        #region __________上传文件__________
        /// <summary>
        /// 上传文件到指定位置
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串，如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标位置，相对路径：如/FTF/FTFDEL/K.pdf</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <param name="SrcFilePath">源文件位置</param>
        /// <returns></returns>
        public bool UploadFtpFile(string BaseUriStr, string AimUriStr, string UserName, string UserPwd, string SrcFilePath)
        {
            string parenturl=AimUriStr.Substring(0,AimUriStr.LastIndexOf('/'));
            if(parenturl==""){parenturl="/";}
            CreateFtpListDirectory(BaseUriStr, parenturl, UserName, UserPwd);

            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.ReadWriteTimeout = 10000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.UploadFile;

            try
            {
                Stream stm = FtpRequest.GetRequestStream();
                byte[] RequestByteArray = File.ReadAllBytes(SrcFilePath);
                stm.Write(RequestByteArray, 0, RequestByteArray.Length);
                stm.Close();

                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                if (FtpResponse.StatusCode == FtpStatusCode.ClosingData)
                {
                    FtpResponse.Close();
                    FileInfo FI = new FileInfo(SrcFilePath);

                    if (GetFtpFileSize(BaseUriStr, AimUriStr, UserName, UserPwd) == FI.Length)
                    {
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                FtpResponse.Close();

                return false;
            }
        }

        #endregion


        #region __________获取文件尺寸__________
        /// <summary>
        /// 获取文件尺寸
        /// 返回文件字节数
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串，如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">目标位置，相对路径：如/FTF/FTFDEL/K.pdf</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  int GetFtpFileSize(string BaseUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.ReadWriteTimeout = 10000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.GetFileSize;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                long FileSize = FtpResponse.ContentLength;
                FtpResponse.Close();

                return Convert.ToInt32(FileSize);
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                FtpResponse.Close();

                return -1;
            }
        }
        #endregion


        #region __________文件重命名__________
        /// <summary>
        /// 文件重命名、文件移动
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串，如ftp://192.168.1.190:21</param>
        /// <param name="SrcUriStr">源位置，相对路径：如/FTF/FTFDEL/K.pdf</param>
        /// <param name="AimUriStr">目标位置，相对路径：如/FTF/FTFDEL/K.pdf</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool RenameFtpFile(string BaseUriStr, string SrcUriStr, string AimUriStr, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, SrcUriStr);
            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.ReadWriteTimeout = 10000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.Rename;
            FtpRequest.RenameTo = AimUriStr;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                if (FtpResponse.StatusCode == FtpStatusCode.FileActionOK)
                {
                    FtpResponse.Close();
                    return true;
                }
                else
                {
                    FtpResponse.Close();
                    return false;
                }
            }
            catch (WebException e)
            {
                int FileSize = GetFtpFileSize(BaseUriStr, SrcUriStr, UserName, UserPwd);
                if (FileSize == -1)
                {
                    return false;
                }
                else
                {
                    FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                    FtpResponse.Close();
                    return false;
                }
            }
        }
        #endregion


        #region __________下载文件__________
        /// <summary>
        /// 下载文件到本地
        /// </summary>
        /// <param name="BaseUriStr">基Uri字符串，如ftp://192.168.1.190:21</param>
        /// <param name="AimUriStr">源位置，相对路径：如/FTF/FTFDEL/K.pdf</param>
        /// <param name="LocalPath">本地文件路径，文件名可以不相同</param>
        /// <param name="UserName">用户名</param>
        /// <param name="UserPwd">用户密码</param>
        /// <returns></returns>
        public  bool DownLoadFtpFile(string BaseUriStr, string AimUriStr, string LocalPath, string UserName, string UserPwd)
        {
            Uri BaseUri = new Uri(BaseUriStr);
            Uri AimUri = new Uri(BaseUri, AimUriStr);

            FtpWebRequest FtpRequest = (FtpWebRequest)WebRequest.Create(AimUri);
            FtpRequest.KeepAlive = true;
            FtpRequest.ReadWriteTimeout = 10000;
            FtpRequest.UsePassive = false;
            NetworkCredential FtpCred = new NetworkCredential(UserName, UserPwd);
            CredentialCache FtpCache = new CredentialCache();
            FtpCache.Add(AimUri, AuthType.Basic.ToString(), FtpCred);
            FtpRequest.Credentials = FtpCache;
            FtpRequest.Method = WebRequestMethods.Ftp.DownloadFile;

            try
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)FtpRequest.GetResponse();
                Stream stm = FtpResponse.GetResponseStream();

                FileStream LocalFile = File.Create(LocalPath);
                byte[] Buff = new byte[500];
                int ReadCount = -1;
                while ((ReadCount = stm.Read(Buff, 0, Buff.Length)) > 0)
                {
                    LocalFile.Write(Buff, 0, ReadCount);
                }
                stm.Close();
                stm.Dispose();

                LocalFile.Close();
                LocalFile.Dispose();

                FtpResponse.Close();

                return true;
            }
            catch (WebException e)
            {
                FtpWebResponse FtpResponse = (FtpWebResponse)e.Response;
                FtpResponse.Close();

                return false;
            }
        }
        #endregion


        #region __________检查服务器是否可用__________
        /// <summary>
        /// 检查服务器连接
        /// </summary>
        /// <param name="IPAddrStr">IP地址字符串</param>
        /// <returns></returns>
        public  bool CheckFtpServer(IPAddress IPAddrStr)
        {
            Ping Pinger = new Ping();
            PingReply Rpy = Pinger.Send(IPAddrStr);
            if (Rpy.Status == IPStatus.Success)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

    }
}
